import 'dart:async';

import 'package:rxdart/rxdart.dart';

import '../../common/test_page.dart';
import '../utils.dart';

class MaterializeTestPage extends TestPage {
  MaterializeTestPage(super.title) {
    test('Rx.materialize.happyPath', () async {
      final stream = Stream.value(1);
      final notifications = <Notification<int>>[];

      stream.materialize().listen(notifications.add, onDone: () {
        expect(notifications);
      });
    });

    test('Rx.materialize.reusable', () async {
      final transformer = MaterializeStreamTransformer<int>();
      final stream = Stream.value(1).asBroadcastStream();
      final notificationsA = <Notification<int>>[],
          notificationsB = <Notification<int>>[];

      stream.transform(transformer).listen(notificationsA.add,
          onDone: () {
            expect(notificationsA);
          });

      stream.transform(transformer).listen(notificationsB.add,
          onDone: () {
            expect(notificationsB);
          });
    });

    test('materializeTransformer.happyPath', () async {
      final stream = Stream.fromIterable(const [1]);
      final notifications = <Notification<int>>[];

      stream
          .transform(MaterializeStreamTransformer<int>())
          .listen(notifications.add, onDone: () {
        expect(notifications);
      });
    });

    test('materializeTransformer.sadPath', () async {
      final stream = Stream<int>.error(Exception());
      final notifications = <Notification<int>>[];

      stream
          .transform(MaterializeStreamTransformer<int>())
          .listen(notifications.add,
          onError: (Object e, StackTrace s) {
            expect(true);
          },onDone: () {
            expect(notifications.length);
            expect(notifications[0].isOnError);
            expect(notifications[1].isOnDone);
          });
    });

    test('materializeTransformer.onPause.onResume', () async {
      final stream = Stream.fromIterable(const [1]);
      final notifications = <Notification<int>>[];

      stream
          .transform(MaterializeStreamTransformer<int>())
          .listen(notifications.add, onDone: () {
        expect(notifications);
      })
        ..pause()
        ..resume();
    });

    test('Rx.materialize accidental broadcast', () async {
      final controller = StreamController<int>();

      final stream = controller.stream.materialize();

      stream.listen(null);
      expect(() => stream.listen(null));

      controller.add(1);
    });

    test('Rx.materialize.nullable', () {
      nullableTest<Notification<String?>>(
            (s) => s.materialize(),
      );
    });
  }

}